#!/usr/bin/python
"""
highlight.py

Syntax highlighting.
"""

import cgi


class Error(Exception):
  pass


# The kind is annotated on the lexer.  The CSS class conforms to pygments style,
# so we can have consistent appeal.

KIND_TO_CLASS = {
    'Keyword': 'k',
    'NamedClass': 'ss',  # Literal.String.Symbol
    'CharLiteral': 'sc',  # literal.string.char
    'Comment': 'c',  # comment
    'Identifier': 'n',  # Name
    'Zero': 'ss',  # Literal.String.Symbol
    'Digit': 'm',  # Literal.Number
    'Operator': 'o',  # Operator
    'RepeatOperator': 'k',  # Keyword
    'Literal': 's',  # Literal.String
    }


class HtmlColorer(object):

  def __init__(self, colors=KIND_TO_CLASS):
    # we can just generated CSS?  There should be no colors at all.
    self.colors = colors
    self.parts = []
    
  def on_token(self, kind, value):
    css_class = self.colors.get(kind)
    if css_class:
      c = cgi.escape(css_class, quote=True)
      v = cgi.escape(value)
      s = '<span class="%s">%s</span>' % (c, v)
    else:
      s = cgi.escape(value)
    self.parts.append(s)

  def render(self):
    # TODO: Should we return css or let people render it?
    return ''.join(self.parts)


class AnsiColorer(object):
  """
  # Another way to do this is as a pipeline.

  c = AnsiColor(colors)
  for out in c(tokens):
    print out

  # We don't need this colorer protocol?
  """
  def __init__(self, colors={}):
    self.colors = colors
    self.parts = []

  def on_token(self, kind, value):
    # all CSS classes begin with x_ for now
    self.parts.append('<span class="x_%s">%s</span>' % (kind, value))

  def render(self):
    # TODO: Should we return css or let people render it?
    return '<pre>' + ''.join(self.parts) + '</pre>'
  

def highlight(tokens, scheme):
  for kind, value, _  in tokens:
    scheme.on_token(kind, value)
  return scheme.render()


def cre_to_html(cre_str):
  """Hack specific to CRE.  Called from tests/cre_examples"""
  from annex import cre_lex

  l = cre_lex.GetLexer()
  tokens = l.lex(cre_str, channel='string')
  scheme = HtmlColorer()
  text = highlight(tokens, scheme)
  return text

